package jinyilw.swing.rlaf.ui;

import jinyilw.swing.ColorTools;
import jinyilw.swing.FontTools;
import jinyilw.swing.graphics.GraphicsTools;
import jinyilw.swing.graphics.RenderingConfig;
import jinyilw.swing.rlaf.UITools;
import jinyilw.swing.rlaf.theme.RThemeColor;

import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.UIResource;
import javax.swing.plaf.basic.BasicGraphicsUtils;
import javax.swing.plaf.basic.BasicTabbedPaneUI;
import javax.swing.text.View;
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.Rectangle;
import java.awt.Stroke;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;

/**
 * @author Jinyi
 */
public class RTabbedPaneUI extends BasicTabbedPaneUI
{
	private static final Color graColor1 = ColorTools.getAlphaColor(Color.white, 20);
	private static final Color graColor2 = ColorTools.getAlphaColor(Color.white, 60);
	static int GAP = 7, ARC = 12;

	private Font font = FontTools.defaultFont;
	private Font selectFont = FontTools.getCustomFont(13);
	private final RenderingConfig renderingConfig = new RenderingConfig();

	public static ComponentUI createUI(JComponent c)
	{
		return new RTabbedPaneUI();
	}

	@Override
	public void installUI(JComponent c)
	{
		super.installUI(c);
		c.setFont(selectFont);
		c.setOpaque(false);
		tabAreaInsets = new Insets(2, 6, 2, 6);
		tabInsets = new Insets(2, 5, 3, 5);
	}

	@Override
	public void update(Graphics g, JComponent c)
	{
		lightHighlight = RThemeColor.colorSet.lineColor;
		Graphics2D g2d = (Graphics2D) g;
		renderingConfig.setAllAAPainting(g2d);
		paint(g, c);
		renderingConfig.resetAllAAPainting(g2d);
	}

	@Override
	protected void paintText(Graphics g, int tabPlacement, Font f,
			FontMetrics metrics, int tabIndex, String title, Rectangle textRect,
			boolean isSelected)
	{
		if (tabPlacement == BOTTOM)
			textRect.y -= 3;
		g.setFont(isSelected ? selectFont : font);
		View v = getTextViewForTab(tabIndex);
		if (v != null)
		{
			v.paint(g, textRect);// html
			return;
		}
		int mnemIndex = tabPane.getDisplayedMnemonicIndexAt(tabIndex);
		if (tabPane.isEnabled() && tabPane.isEnabledAt(tabIndex))
		{
			Color fColor = tabPane.getForegroundAt(tabIndex);
			if (fColor == null || fColor instanceof UIResource)
				g.setColor(RThemeColor.colorSet.textColor);
			else
				g.setColor(fColor);
			BasicGraphicsUtils.drawStringUnderlineCharAt(g, title, mnemIndex,
					textRect.x, textRect.y + metrics.getAscent());
		} else
		{
			g.setColor(RThemeColor.colorSet.transBGColor);
			g.drawString(title, textRect.x + 1,
					textRect.y + metrics.getAscent() + 1);
			g.setColor(RThemeColor.colorSet.unableTextColor);
			g.drawString(title, textRect.x, textRect.y + metrics.getAscent());
		}
	}

	@Override
	protected void paintTabBorder(Graphics g, int tabPlacement, int tabIndex,
			int x, int y, int w, int h, boolean isSelected)
	{
		switch (tabPlacement)
		{
			case LEFT:
				y += 1;
				h -= 2;
				w -= 2;
				break;
			case RIGHT:
				y += 1;
				h -= 2;
				w -= 2;
				break;
			case BOTTOM:
				x += 1;
				h -= 4;
				w -= 2;
				break;
			case TOP:
			default:
				x += 1;
				h -= 4;
				w -= 2;
		}
		int x2 = x + w;
		int y2 = y + h;

		Graphics2D g2d = (Graphics2D) g;
		GradientPaint gp;
		Color color = isSelected ? RThemeColor.transThemeColor : graColor2;
		switch (tabPlacement)
		{
			case LEFT:
				gp = new GradientPaint(x, y, color, x2, y, graColor1);
				g2d.setPaint(gp);
				g2d.fillRoundRect(x, y, w, h, ARC, ARC);
				break;
			case RIGHT:
				gp = new GradientPaint(x, y, graColor1, x2, y, color);
				g2d.setPaint(gp);
				g2d.fillRoundRect(x, y, w, h, ARC, ARC);
				break;
			case BOTTOM:
				gp = new GradientPaint(x, y - 2, graColor1, x, y2, color);
				g2d.setPaint(gp);
				g2d.fillRoundRect(x, y - 2, w, h + 2, ARC, ARC);
				break;
			case TOP:
			default:
				gp = new GradientPaint(x, y, color, x, y2 + 2, graColor1);
				g2d.setPaint(gp);
				g2d.fillRoundRect(x, y, w, h + 2, ARC, ARC);
		}

		if (isSelected)
		{
			Stroke saveStroke = g2d.getStroke();
			g2d.setStroke(GraphicsTools.getLargeStroke());
			g2d.setColor(UITools.isLight()
					? RThemeColor.darkThemeColor
					: RThemeColor.themeColor);
			drawBorder(g2d, tabPlacement, x, y, x2, y2);
			g2d.setStroke(saveStroke);
		} else
		{
			g2d.setColor(RThemeColor.colorSet.lineColor);
			drawBorder(g2d, tabPlacement, x, y, x2, y2);
		}
	}

	private void drawBorder(Graphics2D g2d, int tabPlacement, int x, int y,
			int x2, int y2)
	{
		switch (tabPlacement)
		{
			case LEFT:
				g2d.drawArc(x, y, ARC, ARC, 90, 90);
				g2d.drawArc(x, y2 - ARC, ARC, ARC, 180, 90);
				g2d.drawLine(x, y + GAP, x, y2 - GAP);
				g2d.drawLine(x + GAP, y, x2, y);
				g2d.drawLine(x + GAP, y2, x2, y2);
				break;
			case RIGHT:
				g2d.drawArc(x2 - ARC, y, ARC, ARC, 90, -90);
				g2d.drawArc(x2 - ARC, y2 - ARC, ARC, ARC, -90, 90);
				g2d.drawLine(x2, y + GAP, x2, y2 - GAP);
				g2d.drawLine(x, y, x2 - GAP, y);
				g2d.drawLine(x, y2, x2 - GAP, y2);
				break;
			case BOTTOM:
				g2d.drawLine(x + GAP, y2, x2 - GAP, y2);
				g2d.drawArc(x, y2 - ARC, ARC, ARC, 180, 90);
				g2d.drawArc(x2 - ARC, y2 - ARC, ARC, ARC, -90, 90);
				g2d.drawLine(x, y, x, y2 - GAP);
				g2d.drawLine(x2, y, x2, y2 - GAP);
				break;
			case TOP:
			default:
				g2d.drawLine(x + GAP, y, x2 - GAP, y);
				g2d.drawArc(x, y, ARC, ARC, 90, 90);
				g2d.drawArc(x2 - ARC, y, ARC, ARC, 0, 90);
				g2d.drawLine(x, y + GAP, x, y2);
				g2d.drawLine(x2, y + GAP, x2, y2);
		}
	}

	@Override
	protected void paintContentBorder(Graphics g, int tabPlacement,
			int selectedIndex)
	{
	}

	@Override
	protected void paintTabBackground(Graphics g, int tabPlacement,
			int tabIndex, int x, int y, int w, int h, boolean isSelected)
	{
	}

	@Override
	protected void paintFocusIndicator(Graphics g, int tabPlacement,
			Rectangle[] rects, int tabIndex, Rectangle iconRect,
			Rectangle textRect, boolean isSelected)
	{
	}

	@Override
	protected JButton createScrollButton(int direction)
	{
		return new RArrowButton(direction);
	}

	@Override
	protected PropertyChangeListener createPropertyChangeListener()
	{
		return new RPropertyChangeHandler();
	}

	class RPropertyChangeHandler extends PropertyChangeHandler
	{
		@Override
		public void propertyChange(PropertyChangeEvent e)
		{
			super.propertyChange(e);
			if ("font".equals(e.getPropertyName()))
			{
				Font f = tabPane.getFont();
				if (f == null)
					return;
				selectFont = f;
				font = f.deriveFont(f.getSize() - 1f);
			}
		}
	}
}
